<template>
  <div>
    <el-drawer :visible.sync="drawer" :before-close="handleClose" :with-header="false" size="95%" show-close>
      <div id="gridMap"></div>
      <div class="tootl">
        <span v-if="editPower">
          <el-button v-if="ifEdit" @click="saveEditor" type="success" size="mini" plain round>保存编辑</el-button>
          <el-button v-else @click="openGridWin('add')" type="primary" size="mini" plain round>新增网格</el-button>
        </span>
        <el-upload
          v-if="addressSonFlag === 'son' || editPower"
          action=""
          :limit="1"
          :http-request="importGrid"
          :show-file-list="false"
          :on-exceed="handleExceed"
          ref="import"
          class="upload"
        >
          <el-button type="primary" size="mini" plain round> 导入网格</el-button>
        </el-upload>
        <el-button
          v-if="gridType != 'All'"
          type="success"
          size="mini"
          plain
          round
          style="margin-left: 10px"
          @click="exportGrid"
          >导出网格</el-button
        >
        <el-select
          v-model="mapStyle"
          placeholder="请选择"
          @change="styleChange"
          size="mini"
          style="width: 100px; margin-left: 10px"
        >
          <el-option label="幻影黑" value="dark"> </el-option>
          <el-option label="远山黛" value="whitesmoke"> </el-option>
          <el-option label="雅士灰" value="grey"> </el-option>
          <el-option label="靛青蓝" value="blue"> </el-option>
          <el-option label="极夜蓝" value="darkblue"> </el-option>
        </el-select>
      </div>
      <ul v-if="gridType === 'All'" class="levelBox">
        <li>
          <el-checkbox
            v-model="levelSelect.one"
            size="mini"
            label="单元"
            border
            @change="e => checkChange(e, 1)"
          ></el-checkbox>
        </li>
        <li>
          <el-checkbox
            v-model="levelSelect.two"
            size="mini"
            label="村级"
            border
            @change="e => checkChange(e, 2)"
          ></el-checkbox>
        </li>
        <li>
          <el-checkbox
            v-model="levelSelect.three"
            size="mini"
            label="镇级"
            border
            @change="e => checkChange(e, 3)"
          ></el-checkbox>
        </li>
        <li>
          <el-checkbox
            v-model="levelSelect.four"
            size="mini"
            label="区县级"
            border
            @change="e => checkChange(e, 4)"
          ></el-checkbox>
        </li>
        <li>
          <el-checkbox
            v-model="levelSelect.five"
            size="mini"
            label="市级"
            border
            @change="e => checkChange(e, 5)"
          ></el-checkbox>
        </li>
      </ul>
      <div v-if="gridType === 'duty'" class="searchBox">
        <el-input placeholder="输入单元网格编号" v-model="baseText" size="mini" class="filter-input"> </el-input>
        <el-button icon="el-icon-map-search" type="primary" size="mini" class="baseBut" @click.stop="() => searchBut()"
          >搜索</el-button
        >
      </div>
    </el-drawer>
    <el-dialog :title="(editType === 'edit' ? '编辑' : '新增') + '网格'" :visible.sync="gridDialog" width="500px">
      <div>确认编辑{{ gridForm.adcode }}网格？</div>
      <!-- <el-form :model="gridForm" :rules="gridRules" ref="gridForm" label-width="130px" class="demo-ruleForm">
        <el-form-item v-show="gridForm.adcode" label="网格编码">
          {{ gridForm.adcode }}
        </el-form-item>
        <el-form-item label="网格颜色" prop="fill">
          <el-color-picker v-model="gridForm.fill"></el-color-picker>
        </el-form-item>
        <el-form-item label="网格透明度" prop="fillOpacity">
          <el-input-number size="mini" v-model="gridForm.fillOpacity" :min="0" :max="1" :step="0.1"></el-input-number>
        </el-form-item>
        <el-form-item label="网格边界颜色" prop="stroke">
          <el-color-picker v-model="gridForm.stroke"></el-color-picker>
        </el-form-item>
        <el-form-item label="网格边界透明度" prop="strokeOpacity">
          <el-input-number
            size="mini"
            v-model="gridForm.strokeOpacity"
            :min="0.1"
            :max="1"
            :step="0.1"
          ></el-input-number>
        </el-form-item>
        <el-form-item label="网格边界宽度" prop="strokeWeight">
          <el-input-number size="mini" v-model="gridForm.strokeWeight" :min="1" :max="10"></el-input-number>
        </el-form-item>
      </el-form> -->
      <span slot="footer" class="dialog-footer">
        <el-button v-show="editType === 'edit'" type="danger" @click="gridDelete()">删 除</el-button>
        <el-button @click="gridDialog = false">取 消</el-button>
        <el-button type="primary" @click="createPolygon()">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import * as api from '@/api/map'
import AMapLoader from '@amap/amap-jsapi-loader'
import env from '@/utils/env'
export default {
  props: {
    // 网格编码
    adcode: {
      type: String,
      default: '',
    },
    // 层级
    level: {
      type: Number,
      default: null,
    },
    // 行政连级id
    pid: {
      type: Number,
      default: null,
    },
    // 是否可编辑
    editPower: {
      type: Boolean,
      default: false,
    },
    // 是否显示子集
    addressSonFlag: {
      type: String,
      default: '',
    },
    // 网格类型
    gridType: {
      type: String,
      default: '',
    },
    // 网格名称
    gridName: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      drawer: false,
      // 地图事件
      map: null,
      polyEditor: null,
      // 编辑网格
      gridDialog: false,
      gridForm: {
        adcode: '',
        fill: '',
        fillOpacity: 0.3,
        stroke: '',
        strokeOpacity: 1,
        strokeWeight: 2,
      },
      gridRules: {
        fill: [{ required: true, message: '请选择网格颜色', trigger: 'change' }],
        fillOpacity: [{ required: true, message: '请输入网格透明度', trigger: 'blur' }],
        stroke: [{ required: true, message: '请选择边界颜色', trigger: 'change' }],
        strokeOpacity: [{ required: true, message: '请输入边界透明度', trigger: 'blur' }],
        strokeWeight: [{ required: true, message: '请输入边界宽度', trigger: 'blur' }],
      },
      // 当前编辑的网格对象
      editType: 'add',
      polygonObj: null,
      mapStyle: 'dark',
      upaction:
        process.env.NODE_ENV === 'production'
          ? env.prod.baseUrl
          : process.env.NODE_ENV === 'test'
          ? env.test.baseUrl
          : env.dev.baseUrl,
      ifEdit: false,
      initEdit: true,
      levelSelect: {
        one: true,
        two: true,
        three: true,
        four: true,
        five: true,
      },
      levelBox: [],
      geojson: null,
      baseText: '',
      getStyle: true,
    }
  },
  mounted() {
    this.initColor()
  },
  methods: {
    // 初始化地图
    init() {
      this.initEdit = false
      this.getStyle = true
      this.mapStyle = 'dark'
      AMapLoader.load({
        key: '30f0645cbadb0e5f302e20e86b3e627f',
        version: '2.0',
        plugins: ['AMap.Polygon', 'AMap.PolygonEditor', 'AMap.GeoJSON'], // 需要使用的的插件列表，如比例尺'AMap.Scale'等
      }).then(AMap => {
        this.map = new AMap.Map('gridMap', {
          mapStyle: 'amap://styles/' + this.mapStyle,
          showBuildingBlock: true,
          showLabel: true,
          center: [113.89362474, 23.14630753],
          zoom: 14,
        })
        if (this.editPower) {
          this.initPolygonEdit()
        }
        if (this.gridType === 'administration') {
          this.getBaseGrid()
        } else if (this.gridType === 'All') {
          this.getAllGrid()
        } else if (this.gridType === 'duty') {
          this.getBaseGrid()
          this.getGridBoundary()
        }
      })
    },
    //初始化颜色
    initColor() {
      this.gridForm.fill = this.getCasualeColor()
      this.gridForm.stroke = this.getCasualeColor()
    },
    // 获取随机颜色
    getCasualeColor() {
      let random = Math.random()
      if (random < 0.07) {
        random = Math.random()
      }
      let num = Math.floor(random * 16777215).toString(16)
      if (num.length < 6) {
        num += '1'
      }
      return '#' + num
    },
    // 初始化编辑器
    initPolygonEdit() {
      let that = this
      let createOptions = {
        fillColor: this.gridForm.fill,
        fillOpacity: this.gridForm.fillOpacity,
        strokeColor: this.gridForm.stroke,
        strokeWeight: this.gridForm.strokeWeight,
        strokeOpacity: this.gridForm.strokeOpacity,
      }
      this.polyEditor = new AMap.PolygonEditor(this.map, undefined, { createOptions })
      // 设置新增事件
      this.polyEditor.on('add', function (data) {
        let polygon = data.target
        //添加吸附多边形-卡顿
        that.polyEditor.addAdsorbPolygons(polygon)
        // 设置双击事件
        polygon.on('dblclick', row => that.dblClick(row))
      })
      // 结束编辑
      this.polyEditor.on('end', function (data) {
        let row = data.target._opts
        let path = []
        if (Array.isArray(row.path[0][0][0])) {
          path = row.path
        } else if (Array.isArray(row.path[0][0])) {
          path = [row.path]
        } else {
          let arr = [row.path]
          if (arr[0][arr[0].length - 1] !== arr[0][0]) {
            arr[0].push(arr[0][0])
          }
          path[0] = arr
        }
        let obj = {
          coordinatePath: path,
          fill: row.fillColor,
          fillOpacity: row.fillOpacity,
          stroke: row.strokeColor,
          strokeWidth: row.strokeWeight,
          strokeOpacity: row.strokeOpacity,
          addressPid: that.pid ?? '',
          adcode: that.adcode,
          level: that.addressSonFlag == 'son' ? that.level - 1 : that.level,
        }
        if (that.editType === 'add') {
          api.insertBaseGrid(obj).then(res => {
            if (res.code == '200') {
              row.id = res.data
              that.$message({
                type: 'success',
                message: '保存成功!',
              })
            }
          })
        } else {
          obj.gridId = that.gridForm.id
          api.updateGridNew(obj).then(res => {
            if (res.code == '200') {
              that.$message({
                type: 'success',
                message: '保存成功!',
              })
            }
          })
        }
      })
    },
    /**
     * 初始化网格
     * @param {Object} json 地图数据
     * @returns {class}
     */
    initPolygon(json, level = 0) {
      let that = this
      this.levelBox[level] = new AMap.GeoJSON({
        geoJSON: json,
        getPolygon: function (geojson, lnglats) {
          let pol = new AMap.Polygon({
            path: lnglats,
            fillOpacity: geojson.properties['fill-opacity'] ?? 0.3,
            strokeColor: geojson.properties.stroke ?? that.getCasualeColor(),
            fillColor: geojson.properties.fill ?? that.getCasualeColor(),
            strokeWeight: geojson.properties['stroke-width'] ?? 2,
            zIndex: (that.editPower ? geojson.properties.zIndex : 0) ?? 1,
            id: geojson.id,
            adcode: geojson.properties.adcode,
            // draggable: true,
          })
          if (that.editPower && that.getStyle) {
            that.getStyle = false
            that.gridForm = {
              fill: geojson.properties.fill ?? that.getCasualeColor(),
              fillOpacity: geojson.properties['fill-opacity'] ?? 0.3,
              stroke: geojson.properties.stroke ?? that.getCasualeColor(),
              strokeWeight: geojson.properties['stroke-width'] ?? 2,
              strokeOpacity: 1,
            }
          }
          // 设置双击事件
          if (that.editPower) {
            that.polyEditor.addAdsorbPolygons(pol)
            pol.on('dblclick', row => that.dblClick(row))
          }
          return pol
        },
      })
      if (that.editPower) {
        that.$notify({
          title: '提示',
          position: 'bottom-right',
          message: '双击网格进行编辑网格！',
        })
      }
      that.map.add(this.levelBox[level])
      that.map.setFitView()
    },
    // 获取所有网格边界
    getGridBoundary() {
      let data = {
        levelList: [2, 3, 4, 5],
      }
      api.getAllGrid(data).then(res => {
        if (res.code == '200') {
          this.initBoundary(res.data)
        }
      })
    },
    getAllGrid() {
      let list = [1, 2, 3, 4, 5]
      for (const item of list) {
        api.getAllGrid({ level: item }).then(res => {
          if (res.code == '200') {
            this.initPolygon(res.data, item)
          }
        })
      }
    },
    // 初始化所有边界网格
    initBoundary(json) {
      let that = this
      let geojson = new AMap.GeoJSON({
        geoJSON: json,
        getPolygon: function (geojson, lnglats) {
          let pol = new AMap.Polygon({
            path: lnglats,
            fillOpacity: 0,
            strokeColor: geojson.properties.stroke ?? that.getCasualeColor(),
            strokeWeight: 3,
            zIndex: 0,
          })
          // that.polyEditor.addAdsorbPolygons(pol)
          return pol
        },
      })
      that.map.add(geojson)
    },
    // 网格双击事件
    dblClick(row) {
      let opt = row.target._opts
      this.polygonObj = row.target
      this.openGridWin('edit')
      this.gridForm = {
        adcode: opt.adcode,
        id: opt.id,
        fill: opt.fillColor,
        fillOpacity: opt.fillOpacity,
        stroke: opt.strokeColor,
        strokeOpacity: opt.strokeOpacity,
        strokeWeight: opt.strokeWeight,
      }
    },
    // 打开新建窗口
    openGridWin(e) {
      this.saveEditor()
      this.editType = e
      if (e === 'add') {
        this.gridForm.adcode = ''
        this.polygonObj = null
        if (this.initEdit) {
          this.initEdit = false
          this.gridDialog = true
        } else {
          this.createPolygon()
        }
      } else {
        this.gridDialog = true
      }
    },
    // 确认新建
    createPolygon() {
      // this.$refs.gridForm.validate(valid => {
      //   if (valid) {
      this.ifEdit = true
      if (!this.polygonObj) {
        this.$notify({
          title: '提示',
          position: 'bottom-right',
          message: '点击地图处新增网格点，双击结束编辑！',
        })
        this.initPolygonEdit()
      } else {
        let createOptions = {
          fillColor: this.gridForm.fill,
          fillOpacity: this.gridForm.fillOpacity,
          strokeColor: this.gridForm.stroke,
          strokeWeight: this.gridForm.strokeWeight,
          strokeOpacity: this.gridForm.strokeOpacity,
        }
        Object.assign(this.polygonObj._opts, createOptions)
        this.$notify({
          title: '提示',
          position: 'bottom-right',
          message: '单击白色点可删除标点，点击右上角保存退出编辑！',
        })
      }
      this.polyEditor.setTarget(this.polygonObj ?? null)
      this.polyEditor.open()
      this.gridDialog = false
      //   }
      // })
    },
    // 保存编辑
    saveEditor() {
      this.ifEdit = false
      this.polyEditor.setTarget()
    },
    // 修改地图样式
    styleChange(e) {
      this.map.setMapStyle('amap://styles/' + e)
    },
    // 删除网格
    gridDelete() {
      this.$confirm('此操作将永久删除该网格, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        this.gridDialog = false
        this.map.panBy(1, 1)
        api.delectGrid([this.gridForm.id]).then(res => {
          if (res.code == '200') {
            this.polygonObj.destroy()
            this.$message({
              type: 'success',
              message: '删除成功!',
            })
          }
        })
      })
    },
    // 获取指定网格
    getBaseGrid() {
      let data = {
        adcode: this.adcode ?? '',
        level: this.addressSonFlag == 'son' ? this.level - 1 : this.level,
        addressPid: this.pid ?? '',
        addressSonFlag: this.addressSonFlag ?? '',
      }
      api.getAllGrid(data).then(res => {
        if (res.code == '200') {
          this.initPolygon(res.data)
        }
      })
    },
    // 关闭
    handleClose() {
      this.drawer = false
      this.levelBox = []
    },
    // 导出
    exportGrid() {
      let data = {
        addressPid: this.pid ?? '',
        adcode: this.adcode ?? '',
        level: this.addressSonFlag == 'son' ? this.level - 1 : this.level,
        addressSonFlag: this.addressSonFlag ?? '',
      }
      api.gridExport(data).then(res => {
        let blob = new Blob([res], { type: 'application/vnd.ms-excel' })
        let elink = document.createElement('a')
        elink.download = '地图导出数据.json'
        elink.style.display = 'none'
        elink.href = URL.createObjectURL(blob)
        document.body.appendChild(elink)
        elink.click()
        document.body.removeChild(elink)
      })
    },
    //文件超出个数限制时的钩子
    handleExceed() {
      this.$message({
        type: 'warning',
        message: '只能上传一个文件!',
      })
    },
    // 导入
    importGrid(file) {
      let fd = new FormData()
      let token = localStorage.getItem('Authorization')
      fd.append('file', file.file)
      fd.append('addressPid', this.pid ?? '')
      fd.append('adcode', this.adcode)
      fd.append('level', this.addressSonFlag == 'son' ? this.level - 1 : this.level)
      fetch(this.upaction + '/grid/coordinate/import', {
        method: 'POST',
        body: fd,
        headers: {
          Authorization: token,
        },
      }).then(res => {
        this.$refs.import.clearFiles()
        this.getBaseGrid()
        if (res.code === '200') {
          this.$message({
            type: 'success',
            message: '导入成功',
          })
        }
      })
    },
    checkChange(e, level) {
      if (e) {
        this.levelBox[level].show()
      } else {
        this.levelBox[level].hide()
      }
    },
    searchBut() {
      let gridList = this.levelBox[0]._overlays
      for (const item of gridList) {
        if (this.baseText == item._opts.adcode) {
          this.map.setFitView(item)
        }
      }
    },
  },
}
</script>

<style lang="scss" scoped>
#gridMap {
  width: 100%;
  height: 100vh;
}
.tootl {
  position: fixed;
  display: block;
  right: 20px;
  top: 20px;
  border-radius: 6px;
  background-color: white;
  box-shadow: 0px 5px 5px 0px rgb(0 0 0 / 50%);
  padding: 10px;
}
.upload {
  display: inline-block;
  margin-left: 10px;
}
.levelBox {
  position: fixed;
  right: 20px;
  bottom: 20px;
  border-radius: 6px;
  background-color: white;
  box-shadow: 0px 5px 5px 0px rgb(0 0 0 / 50%);
  padding: 10px;
  li {
    margin-bottom: 5px;
    list-style-type: none;
  }
}
.searchBox {
  position: fixed;
  display: flex;
  left: 7%;
  top: 20px;
  border-radius: 6px;
  background-color: white;
  box-shadow: 0px 5px 5px 0px rgb(0 0 0 / 50%);
  padding: 10px;
  .filter-input {
    display: inline-block;
    margin-right: 10px;
  }
}
</style>
